package org.wak.gui.scumm
{
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	import org.wak.gui.events.GuiEvent;
	import org.wak.inventory.Inventory;
	import org.wak.inventory.InventoryItem;
	import org.wak.inventory.events.InventoryEvent;
	import org.wak.utils.IIterator;
	import org.wak.utils.WakSimpleButton;

	/**
	 * Class to render the player's inventory in the scumm gui. 
	 * 
	 */	
	public class ScummInventoryDisplay extends Sprite
	{
		// rows of items to display
		protected var mRows:int = 0 ;
		// columns of items to display
		protected var mCols:int = 0 ;
		
		// width of each item in pixels
		protected var mItemWidth:int = 0 ;
		
		// height of each item in pixels
		protected var mItemHeight:int = 0 ;
		
		// pixels which separates the item rows
		protected var mRowsSeparator:int = 2 ;
		
		// pixels which separates the item columns
		protected var mColsSeparator:int = 1 ;
		
		// the inventory to render.
		protected var mInventory:Inventory = null ;
		
		// arrow up to scroll the inventory.
		protected var mArrowUp:WakSimpleButton = null ;
		
		// Arrow down to scroll the inventory.
		protected var mArrowDown:WakSimpleButton = null ;
		
		protected var mItemsArray:Array = null ;
		
		// Asoc array from Sprite reference to InventoryItem.
		protected var mSpriteToItem:Array = null ;
		
		// starting x to draw the items.
		protected var mItemsX:Number = 0 ;
		// starting y to draw the items.
		protected var mItemsY:Number = 0 ;
		
		protected var mInventoryMask:Sprite = null ;
		
		// the mouse selected item by over or click.
		protected var mSelectedItem:Sprite = null;
		
		// layer where the items are added to easily handle the scroll.
		protected var mScrollingLayer:Sprite = null ;
		
		protected var mTotalRows:int = 0;
		
		/**
		 * Constructor 
		 * @param pInventory the inventory of the player's character
		 * @param pRows visible rows that the inventory will have on screen.
		 * @param pCols visible columns that the inventory will have on screen.
		 * @param pItemWidth max width in pixels of an item on the inventory
		 * @param pItemHeight max height in pixels of an item on the inventory
		 * 
		 */		
		public function ScummInventoryDisplay(pInventory:Inventory, pRows:int = 2, pCols:int = 4, pItemWidth:int = 70, pItemHeight:int = 44)
		{
			super();
			mInventory = pInventory ;
			mRows = pRows ;
			mCols = pCols ;
			mItemWidth = pItemWidth ;
			mItemHeight = pItemHeight ;
			mInventory = pInventory ;
			
			mScrollingLayer = new Sprite
			this.addChild(mScrollingLayer);
			
			mItemsArray = new Array();
			mSpriteToItem = new Array();
			
			addEventListener(Event.ADDED_TO_STAGE, OnAddedToStage );
		}
		
		/**
		 * Button to scroll up the inventory. 
		 * @param value
		 * 
		 */		
		public function set arrowUp(value:WakSimpleButton):void
		{
			mArrowUp = value ;
		}
		
		/**
		 * Button to scroll down the inventory.
		 * @param value
		 * 
		 */		
		public function set arrowDown(value:WakSimpleButton):void
		{
			mArrowDown = value ;
		}
		
		protected function OnAddedToStage(event:Event):void
		{
			this.removeEventListener(Event.ADDED_TO_STAGE, OnAddedToStage );
			
			// Create the scrolling buttons
			if(mArrowDown == null)
				mArrowDown = CreateDownArrow();
			addChild(mArrowDown);
			
			mArrowDown.addEventListener(MouseEvent.MOUSE_UP, OnScrollDown );
				
			if(mArrowUp == null)
				mArrowUp = CreateUpArrow();
			addChild(mArrowUp);
			mArrowUp.addEventListener(MouseEvent.MOUSE_UP, OnScrollUp );
			
			mItemsX = mArrowUp.x + mArrowUp.width + 1 ;
			mItemsY = mArrowUp.y + 1 ;
			
			// Set the scrolling mask
			mInventoryMask = new Sprite() ;
			mInventoryMask.graphics.beginFill(0xFFFFFF);
			mInventoryMask.graphics.drawRect(0,0,mArrowUp.width + mCols * (mItemWidth + mColsSeparator), mArrowUp.height + mRows * ( mItemHeight + mRowsSeparator) );
			mInventoryMask.graphics.endFill() ;
			
			mInventoryMask.x = 0 ;
			mInventoryMask.y = 0 ;
			this.addChild(mInventoryMask);
			this.mask = mInventoryMask ;
			
			// fill the inventory
			FillInventory( mInventory.GetItems() );
			
			// enable or disable scrolling buttons.
			if( (mItemsArray.length / mCols) > mRows )
			{
				mArrowDown.enabled = true ;
			}
			
			mInventory.addEventListener(InventoryEvent.ITEM_ADDED, OnItemAdded );
			mInventory.addEventListener(InventoryEvent.ITEM_REMOVED,OnItemRemoved );
			
			
			this.addEventListener(Event.REMOVED_FROM_STAGE, OnRemovedToStage );
		}
		
		protected function OnRemovedToStage(event:Event):void
		{
			this.removeEventListener(Event.REMOVED_FROM_STAGE, OnRemovedToStage );
			
			for each( var item:Sprite in mItemsArray)
			{
				item.addEventListener(MouseEvent.MOUSE_OVER, OnItemMouseOver );
				item.addEventListener(MouseEvent.MOUSE_OUT, OnItemMouseOut );
				item.addEventListener(MouseEvent.CLICK, OnItemMouseClick );
			}
			
			mInventory.removeEventListener(InventoryEvent.ITEM_ADDED, OnItemAdded );
			mInventory.removeEventListener(InventoryEvent.ITEM_REMOVED,OnItemRemoved );
			this.addEventListener(Event.ADDED_TO_STAGE, OnAddedToStage );
		}
		
		protected function OnItemMouseOver(event:MouseEvent):void
		{
			if(mSelectedItem != event.target )
			{
				mSelectedItem = event.target as Sprite;
				var fItem:InventoryItem = mSpriteToItem[mSelectedItem.name] as InventoryItem;
				//trace("OnItemMouseOver "+ fItem.interactableId );
				var fEvent:GuiEvent = new GuiEvent( GuiEvent.INVENTORY_ITEM_OVER,"",fItem);
				this.dispatchEvent( fEvent );
			}
		}
		
		protected function OnItemMouseOut(event:MouseEvent):void
		{
			if( !mSelectedItem.hitTestPoint( event.stageX, event.stageY, true) )
			{
				var fTarget:Sprite = event.target as Sprite;
				var fItem:InventoryItem = mSpriteToItem[fTarget.name] as InventoryItem;
				var fEvent:GuiEvent = new GuiEvent( GuiEvent.INVENTORY_ITEM_OUT,"",fItem);
				this.dispatchEvent( fEvent );
				
				mSelectedItem = null ;
			}
		}
		
		protected function OnItemMouseClick(event:MouseEvent):void
		{
		
			mSelectedItem = event.target as Sprite;
			var fItem:InventoryItem = mSpriteToItem[mSelectedItem.name] as InventoryItem;
			var fEvent:GuiEvent = new GuiEvent( GuiEvent.INVENTORY_ITEM_SELECTED,"",fItem);
			this.dispatchEvent( fEvent );
		
		}
		
		protected function FillInventory( pItItems:IIterator ):void
		{
			var fNewItem:InventoryItem = null ;
			var fItemDisplay:Sprite = null ;
			
			var fCurrentX:Number = mItemsX ;
			var fCurrentY:Number = mItemsY ;
			
			var fRowCounter:int = 0 ;
			var fColCounter:int = 0 ;
			
			while(pItItems.hasNext())
			{
				fNewItem = pItItems.next() as InventoryItem ;
				fItemDisplay = fNewItem.itemDisplay ;
				fItemDisplay.x = mItemsX + (fColCounter * mItemWidth) + mColsSeparator ; 
				fItemDisplay.y = mItemsY + (fRowCounter * mItemHeight) + mRowsSeparator ;
				
				mScrollingLayer.addChild(fItemDisplay);
				mItemsArray.push( fItemDisplay );
				mSpriteToItem[fItemDisplay.name] = fNewItem ;
				fItemDisplay.addEventListener(MouseEvent.MOUSE_OVER, OnItemMouseOver );
				fItemDisplay.addEventListener(MouseEvent.MOUSE_OUT, OnItemMouseOut );
				fItemDisplay.addEventListener(MouseEvent.CLICK, OnItemMouseClick );
				
				fColCounter++ ;
				if( fColCounter >= mCols )
				{
					fRowCounter++ ;
					fColCounter = 0 ;
				}
				
				
			}
			
			mTotalRows = mItemsArray.length / mCols ;
			
		}
		
		protected function OnItemAdded(event:InventoryEvent):void
		{
	
			var fNewItem:InventoryItem = event.inventoryItem ;
			
			mItemsArray.push( fNewItem.itemDisplay );
			mSpriteToItem[fNewItem.itemDisplay.name] = fNewItem ;
			
			RefreshItemsPositions( mItemsArray );
			
			var fNewItemRow:int = (mScrollingLayer.y + fNewItem.itemDisplay.y) / (mItemHeight + mRowsSeparator) ;
			
			//trace("OnItemAdded:"+ fNewItemRow );
			
			fNewItem.itemDisplay.addEventListener(MouseEvent.MOUSE_OVER, OnItemMouseOver );
			fNewItem.itemDisplay.addEventListener(MouseEvent.MOUSE_OUT, OnItemMouseOut );
			fNewItem.itemDisplay.addEventListener(MouseEvent.CLICK, OnItemMouseClick );
			
			var fItemBottomLine:Number = this.y + mScrollingLayer.y + fNewItem.itemDisplay.y  ;
			var fInventoryBottomLine:Number = this.y + (mRows * mItemHeight) ;
			
			while(fItemBottomLine > fInventoryBottomLine )
			{
				//trace("while OnItemAdded:"+ fNewItemRow );
				ScrollDown();
				UpdateScrollButtons(); 
				fItemBottomLine = this.y + mScrollingLayer.y + fNewItem.itemDisplay.y  ;
			}
			
			
		}
		
		protected function OnItemRemoved(event:InventoryEvent):void
		{
			var fRemovedItem:InventoryItem = event.inventoryItem ;
			var fIndex:int = mItemsArray.indexOf(fRemovedItem.itemDisplay);
			
			if(fIndex >= 0)
			{
				mItemsArray.splice(fIndex,1);
				mSpriteToItem[fRemovedItem.itemDisplay.name] = null ;
				if(mScrollingLayer.contains( fRemovedItem.itemDisplay ) )
					mScrollingLayer.removeChild( fRemovedItem.itemDisplay);
					
				fRemovedItem.itemDisplay.removeEventListener(MouseEvent.MOUSE_OVER, OnItemMouseOver );
				fRemovedItem.itemDisplay.removeEventListener(MouseEvent.MOUSE_OUT, OnItemMouseOut );
				fRemovedItem.itemDisplay.removeEventListener(MouseEvent.CLICK, OnItemMouseClick );
				
				RefreshItemsPositions( mItemsArray );
			}
		}
		
		protected function RefreshItemsPositions(pItemsArray:Array):void
		{
			var fRowCounter:int = 0 ;
			var fColCounter:int = 0 ;
			
			var fFirstItem:Sprite = mItemsArray[0] as Sprite ;
			
			for each( var item:Sprite in pItemsArray)
			{
				item.x = mItemsX + (fColCounter * mItemWidth) + mColsSeparator ; 
				item.y = mItemsY + (fRowCounter * mItemHeight) + mRowsSeparator ;
				
				if( !mScrollingLayer.contains(item) )
					mScrollingLayer.addChild(item);
					
				fColCounter++ ;
				if( fColCounter >= mCols )
				{
					fRowCounter++ ;
					fColCounter = 0 ;
				}
				
			}				
		}
		
		
		
		protected function CreateUpArrow():WakSimpleButton
		{
			var fBtn:WakSimpleButton = null 
			 
			var fUp:Sprite = DrawDownArrow(0x120012,0x8a348d);
			fUp.rotation = 180 ;
			fUp.x = fUp.width + 1; 
			fUp.y = fUp.height ;
			
			var fOver:Sprite = DrawDownArrow(0x120012,0x8a348d);
			fOver.rotation = 180 ;
			fOver.x = fUp.width + 1; 
			fOver.y = fUp.height ;
			
			var fDown:Sprite = DrawDownArrow(0x120012,0x8a348d);
			fDown.rotation = 180 ;
			fDown.x = fUp.width + 1; 
			fDown.y = fUp.height ;
			
			fBtn = new WakSimpleButton( fUp, fOver, fDown);
			fBtn.y = 2 ;
			fBtn.enabled = false ;
			return fBtn ;
		}
		
		protected function CreateDownArrow():WakSimpleButton
		{
			var fUp:Sprite = DrawDownArrow(0x120012,0x8a348d);
			var fOver:Sprite = DrawDownArrow(0x120012,0x8a348d);
			var fDown:Sprite = DrawDownArrow(0x120012,0x8a348d);
			var fBtn:WakSimpleButton = new WakSimpleButton(fUp,fOver,fDown);
			
			fBtn.y = fBtn.height + 2 ;
			fBtn.enabled = false ;
			return fBtn;
			  
		}
		
		protected function DrawDownArrow(pBgColor:uint, pArrowColor:uint):Sprite
		{
			var fArrow:Sprite = new Sprite();
			fArrow.graphics.beginFill(pBgColor);
			fArrow.graphics.drawRect(0,0,26,44);
			fArrow.graphics.endFill();
			
			fArrow.graphics.lineStyle(1,pArrowColor);
			fArrow.graphics.moveTo(9,2);
			fArrow.graphics.lineTo(9,25);
			
			fArrow.graphics.moveTo(9,25);
			fArrow.graphics.lineTo(1,25);
			
			fArrow.graphics.moveTo(1,25);
			fArrow.graphics.lineTo(13,38);
			
			fArrow.graphics.moveTo(13,38);
			fArrow.graphics.lineTo(26,25);
			
			fArrow.graphics.moveTo(26,25);
			fArrow.graphics.lineTo(18,25);
			
			fArrow.graphics.moveTo(18,25);
			fArrow.graphics.lineTo(18,2);
			
			fArrow.graphics.moveTo(18,2);
			fArrow.graphics.lineTo(9,2);
			fArrow.graphics.endFill();
			
			return fArrow ;
			
		}
		
		protected function OnScrollDown(event:Event):void
		{
			//trace("OnScrollDown");
			if( !(mArrowDown.enabled) )
			{
				return ;
			}
			
			ScrollDown();
			
			
		}
		
		protected function OnScrollUp(event:Event):void
		{
			//trace("OnScrollUp");
			if( !(mArrowUp.enabled) )
			{
				return ;
			}
			
			ScrollUp();
		}
		
		protected function ScrollDown():void
		{
			mScrollingLayer.y -= mItemHeight + mRowsSeparator ;
			
			UpdateScrollButtons();
			
		}
		
		protected function UpdateScrollButtons():void
		{
			var fLastItem:DisplayObject = mItemsArray[mItemsArray.length -1] ;
			
			var fLastItemRow:int = (mScrollingLayer.y + fLastItem.y) / (mItemHeight + mColsSeparator) ;
			if( fLastItemRow >= mRows )
			{
				mArrowDown.enabled = true ;
				
			}
			else
			{
				mArrowDown.enabled = false ;
			}
			
			var fFirstItem:DisplayObject = mItemsArray[0] ;
			
			if( (fFirstItem.y + mScrollingLayer.y) < 0 )
			{
				mArrowUp.enabled = true ;
			}
			else if((fFirstItem.y + mScrollingLayer.y) >= 0 )
			{
				mArrowUp.enabled = false ;
			}
			
		}
		
		protected function ScrollUp():void
		{
			mScrollingLayer.y += mItemHeight + mRowsSeparator ;
			UpdateScrollButtons();
		}
		
	}
}